package com.jy.modules.cims.creditright.service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.exception.CimsException;
import com.jy.modules.cims.common.sysUtils.CollectionsUtils;
import com.jy.modules.cims.common.sysUtils.DateTimeUtils;
import com.jy.modules.cims.common.sysUtils.SearchParamUtil;
import com.jy.modules.cims.component.plan.ICPlan;
import com.jy.modules.cims.data.dao.CostPlanDao;
import com.jy.modules.cims.data.dao.CreditRightDao;
import com.jy.modules.cims.data.dto.CreditDetailDto;
import com.jy.modules.cims.data.dto.CreditDetailQueryDto;

@Service("com.jy.modules.cims.creditright.service.PlanService")
public class PlanService {
	private static final Logger logger = LoggerFactory.getLogger(PlanService.class);
	private static int DEFAULT_PAGE_SIZE = 50000;

	@Autowired
	private CostPlanDao costPlanDao;

	@Autowired
	private CreditRightDao creditRightDao;

	@Autowired
	@Qualifier("com.jy.modules.cims.component.plan.CPlanImpl")
	private ICPlan cPlan;

	@Autowired
	@Qualifier("com.jy.modules.cims.creditright.service.CreditRightService")
	private CreditRightService creditRightService;
	
	/**
	 * @Description 生成还款计划和计算计划
	 * @param creditDetailDto
	 *            债权明细
	 * @throws Exception
	 */
	public void doProcessPlan(final CreditDetailDto creditDetailDto) throws Exception {
		cPlan.doCreatPlan(creditDetailDto);
		cPlan.doChangePlan(creditDetailDto);
	}

	/**
	 * @Description 重置结算计划，还款计划
	 * @param transferId
	 * @throws Exception
	 * @author zhangmi
	 * @date 2016-3-8
	 */
	public void doRestPlanByTransferId(final String transferId) throws Exception {
		costPlanDao.deleteTCMmCostPlanByTransferId(transferId);
		costPlanDao.deleteTCMmRefundPlanByTransferId(transferId);

		CreditDetailDto creditDetailDto = new CreditDetailDto();
		creditDetailDto.setTransferId(transferId);
		List<CreditDetailDto> creditRightList = creditRightDao.searchCreditDetailForCreatPlan(SearchParamUtil.getSearchParam(creditDetailDto));
		if (CollectionsUtils.isEmpty(creditRightList)) {
			throw new CimsException(java.text.MessageFormat.format("转让编号【{0}】的债权不符合重置结算计划和还款计划(贷款转出和债权转让交易已确认的债权，并且合约配置债权结算参数的月还处理方式 )！",
					new Object[] { creditDetailDto.getTransferId() }));
		}

		creditDetailDto = creditRightList.get(0);
		cPlan.doCreatPlan(creditDetailDto);
		cPlan.doChangePlan(creditDetailDto);
	}

	/**
	 * @Description 按照合约的结算参数重新计算结算计划返回金额和匹配金额
	 * @param creditDetailDto
	 *            债权明细
	 * @throws Exception
	 */
	public void doUpdateCostPlanAmount(final CreditDetailQueryDto creditDetailQueryDto) throws Exception {
		costPlanDao.updateCostPlanForNormalSettle(SearchParamUtil.getSearchParam(creditDetailQueryDto));
		costPlanDao.updateCostPlanForAdcanceFinish(SearchParamUtil.getSearchParam(creditDetailQueryDto));
	}

	/**
	 * @Description 分页生成还款计划和计算计划
	 * @return
	 * @throws Exception
	 */
	public List<String> buildPlan() throws Exception {
		List<String> errorMessageList = new ArrayList<String>();
		CreditDetailDto creditDetailDTO = new CreditDetailDto();
		// 查询符合生成还款计划和结算计划的债权明细
		int totalCount = creditRightDao.getCreditDetailCountForCreatPlan(SearchParamUtil.getSearchParam(creditDetailDTO)).intValue();
		if (totalCount <= 0) {
			return errorMessageList;
		}

		// 计算分页
		int pageSum = totalCount / DEFAULT_PAGE_SIZE;
		pageSum = (totalCount % DEFAULT_PAGE_SIZE == 0) ? pageSum : pageSum + 1;
		List<CreditDetailDto> creditRightList = null;
		Map<String, Object> searchParams = null;
		for (int index = 1; index <= pageSum; index++) {
			logger.info("==>>>>>>>>>>>>>>>>>>>生成还款计划和计算计划处理， 页数：" + index);
			searchParams = new HashMap<String, Object>();
			searchParams.put("dto", creditDetailDTO);
			searchParams.put("start", (index - 1) * DEFAULT_PAGE_SIZE + 1);
			searchParams.put("end", index * DEFAULT_PAGE_SIZE);
			// 查询符合生成还款计划和结算计划的债权明细
			creditRightList = creditRightDao.searchCreditDetailForCreatPlan(searchParams);
			creditRightList = setCreditDetailDto(creditRightList);

			for (CreditDetailDto creditDetailDto : creditRightList) {
				String errorMessage = MessageFormat.format("债权编号【{0}】，转让编号【{1}】的结算计划生成失败:", new Object[] { creditDetailDto.getCreditCode(),
						creditDetailDto.getTransferId() });
				try {
					cPlan.doCreatPlan(creditDetailDto);
					cPlan.doChangePlan(creditDetailDto);
				} catch (Exception e) {
					logger.error(errorMessage, e);
					errorMessageList.add(errorMessage + e.getMessage());
				}
			}
			logger.info("==<<<<<<<<<<<<<<<<<<<生成还款计划和计算计划处理， 页数：" + index);
		}

		return errorMessageList;
	}

	/**
	 * 
	 * @param detailList
	 * @return
	 */
	private List<CreditDetailDto> setCreditDetailDto(List<CreditDetailDto> detailList) {
		if (CollectionsUtils.isEmpty(detailList)) {
			return null;
		}

		List<CreditDetailDto> filterList = new ArrayList<CreditDetailDto>();
		for (CreditDetailDto creditDetailDto : detailList) {
			String coreCreditStatus = creditDetailDto.getCoreCreditStatus();
			if ((CimsConstant.CORE_CREDIT_STATUS_SETTLE_AHEAD.equals(coreCreditStatus)
					|| CimsConstant.CORE_CREDIT_STATUS_SETTLE_CANCEL.equals(coreCreditStatus)
					|| CimsConstant.CORE_CREDIT_STATUS_SETTLE_RECOMBINE.equals(coreCreditStatus)
					|| CimsConstant.CORE_CREDIT_STATUS_SETTLE_EXHIBITION.equals(coreCreditStatus)
					|| CimsConstant.CORE_CREDIT_STATUS_SETTLE_CHANGEDATE.equals(coreCreditStatus)) 
					&& (null == creditDetailDto.getBizDate())) {
				filterList.add(creditDetailDto);
			}
		}
		if (CollectionsUtils.isEmpty(filterList)) {
			return detailList;
		}

		Map<String, Object> bizDateMap = new HashMap<String, Object>();
		List<CreditDetailDto> updateList = creditRightService.getUpdateCreditDetail(filterList);
		if (CollectionsUtils.isNotEmpty(updateList)) {
			for (CreditDetailDto creditDetailDto : updateList) {
				bizDateMap.put(creditDetailDto.getTransferId(), creditDetailDto.getBizDate());
			}
		}

		List<CreditDetailDto> newList = new ArrayList<CreditDetailDto>();
		for (CreditDetailDto creditDetailDto : detailList) {
			Date bizDate = (bizDateMap.get(creditDetailDto.getTransferId()) == null) ? (DateTimeUtils.addDays(new Date(), -1)) : ((Date) bizDateMap.get(creditDetailDto.getTransferId()));
			creditDetailDto.setBizDate(bizDate);
			newList.add(creditDetailDto);
		}

		bizDateMap.clear();
		bizDateMap = null;

		return newList;
	}
}
